import java.io.*;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.*;

class RSAexpr{
	Object sendmes;
	Object receivemes;
	BigInteger encrmes;
	BigInteger encrint;
	RSAPublicKeySpec publicKey;
	RSAPrivateKeySpec privateKey;
	RSAexpr(Object msg)
	{
		try {

			KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
			KeyFactory fact = KeyFactory.getInstance("RSA");
			kpg.initialize(2048);
			KeyPair kp=kpg.generateKeyPair();
			publicKey=fact.getKeySpec(kp.getPublic(),RSAPublicKeySpec.class);
			privateKey=fact.getKeySpec(kp.getPrivate(),RSAPrivateKeySpec.class);
//			System.out.println(publicKey.getModulus());
//			System.out.println(publicKey.getPublicExponent());
//			System.out.println(privateKey.getModulus());
//			System.out.println(privateKey.getPrivateExponent());
			send(msg);
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
	public void send(Object msg)
	{
		sendmes=msg;
		System.out.println((Message)sendmes);
		encrypt();
	}
	private void encrypt()
	{
		try {
			ByteArrayOutputStream bo = new ByteArrayOutputStream();
			ObjectOutputStream oo = new ObjectOutputStream(bo);
	        oo.writeObject(sendmes);
			byte[] plaintext=bo.toByteArray();
			BigInteger plainint=new BigInteger(1,plaintext);
			encrint=plainint.modPow(publicKey.getPublicExponent(),publicKey.getModulus());
			System.out.println(plainint);
//			System.out.println(encrint);
			encrmes=encrint;
//			System.out.println(encrmes);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void decrypt()
	{

		try {
			BigInteger encrint=encrmes;
			BigInteger plainint=encrint.modPow(privateKey.getPrivateExponent(),privateKey.getModulus());
			System.out.println(plainint);
//			System.out.println(encrint);
			byte[] plaintext1=plainint.toByteArray();
			byte[] plaintext=plaintext1;
			if(plaintext1[0]==0)
				plaintext=new byte[plaintext1.length-1];
			System.arraycopy(plaintext1, 1, plaintext, 0, plaintext.length);
	        ByteArrayInputStream bi = new ByteArrayInputStream(plaintext);
	        ObjectInputStream oi = new ObjectInputStream(bi);
	        receivemes=oi.readObject();
			System.out.println((Message)receivemes);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
}
public class maintest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//ClientLoginMessage shit=new ClientLoginMessage("wuyiyao","123456");
		Message msg=new Message("wuyiyao","xiedage","1","2","I need a job!");
		//String diu="shit";
		RSAexpr lala=new RSAexpr(msg);
		lala.decrypt();
		
	}

}
